/*
 * Packet.cpp
 *
 *  Created on: 26.10.2012
 *      Author: Sven
 */

#include "../header/main.h"

queue<CPacket*>	CPacket::m_rcvqueue;
queue<CPacket*>	CPacket::m_sendqueue;

CPacket::CPacket(BASE_PACKET* packet, CSession* session)
{
	m_packet = packet;
	m_session = session;
	m_size = packet->size-3;
}

CPacket::CPacket(unsigned char type, short size, CSession* session)
{
	m_session = session;
	m_packet = (BASE_PACKET*)new char[3+size];
	m_packet->size = 3+size;
	m_packet->type = type;
	m_size = size;
}

CPacket::~CPacket()
{
	if(m_packet != 0)
		delete m_packet;
}

void CPacket::setbyte(int index, unsigned char data)
{
	if(!m_packet)
		return;

	if(index >= m_size)
		return;

	m_packet->data[index] = data;
}

void CPacket::setdata(int index, int data)
{
	if(!m_packet)
		return;

	if(index >= m_size)
		return;

	memset(&m_packet->data[index], data, m_size-index);
}

void CPacket::setranddata(int index)
{
	if(!m_packet)
		return;

	if(index >= m_size)
		return;

	for(; index < m_size; index++)
	{
		m_packet->data[index] = rand() % 6;
	}
}

void CPacket::appenddata(int index, char* buffer, int size)
{
	if(!m_packet)
		return;

	if(index >= m_size)
		return;

	if((index+size) > m_size)
		return;

	memcpy(&m_packet->data[index], buffer, size);
}

void CPacket::push(CPacket* packet)
{
	if(packet)
		m_sendqueue.push(packet);
}

CPacket* CPacket::pull()
{
	if(!m_rcvqueue.empty())
	{
		CPacket* packet = CPacket::m_rcvqueue.front();
		CPacket::m_rcvqueue.pop();
		return packet;
	}

	return 0;
}

void CPacket::handle()
{
	// Debugging
	/*cout << "rec: " << (int)m_packet->size << endl;

	for(int n = 0; n < (int)m_packet->size; n++)
	{
		cout << setw(2) << setfill('0') << hex << ((unsigned int)((char*)m_packet)[n] & 0xFF) << " ";
		if((n+1) % 16 == 0)
			cout << endl;
	}
	cout << endl;*/

	// Handling
	switch(m_packet->type)
	{
	case PACKET_LOGOUT:
		{
			cout << "Logged out: " << m_session->getplayer()->getnick() << endl;
			CSession::m_sessions.erase(m_session->getip());
			delete m_session;
		}
		break;
	case PACKET_MAPDATA:
		{
			CPacket* packet = new CPacket(PACKET_MAPDATA, 20*20+1, m_session);
			packet->setbyte(0, m_packet->data[0]);
			packet->setranddata(1);

			/*cout << "Mapdata sent: " << (int)packet->getpacket()->data[0] << " / " << packet->getpacket()->size << endl;

			for(int n = 0; n < (int)packet->getpacket()->size; n++)
				{
					cout << setw(2) << setfill('0') << hex << ((unsigned int)((char*)packet->getpacket())[n] & 0xFF) << " ";
					if((n+1) % 16 == 0)
						cout << endl;
				}*/

			push(packet);
		}
		break;
	default:
	case PACKET_KEEPALIVE:
		{
			CPacket* packet = new CPacket(PACKET_KEEPALIVE, 0, m_session);
			push(packet);
		}
		break;
	case PACKET_STRING:
		{
			char* str = new char[m_packet->size-3+1];
			memcpy(str, m_packet->data, m_packet->size-3);
			str[m_packet->size-3] = 0;

			string chat(m_session->getplayer()->getnick());
			chat.append(": ");
			chat.append(str);

			cout << chat << endl;

			CPacket* packet = new CPacket(PACKET_STRING, chat.length(), 0);
			packet->appenddata(0, (char*)chat.c_str(), chat.length());

			push(packet);
		}
		break;
	}
}
